home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / 3DGPL.ZIP / 3DGPL / TEXT / 1.TXT < prev    next >
Text File  |  1995-06-21  |  22KB  |  437 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.                             Hardware interface.
  7.                            ---------------------
  8.  
  9.  
  10.  
  11.  
  12.  
  13.                                   Real computer scientists despise
  14.                                   the idea of actual hardware.  Hardware
  15.                                   has limitations, software doesn't.
  16.                                   It's a real shame that Turing
  17.                                   machines are so poor at I/O.
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24. What does any graphics product start with? Well, it is the surface things
  25. are being rendered on. We would be talking about raster graphics, the
  26. one which is used almost in all cases nowadays. The idea behind it is that
  27. the image is composed of little square cells - pixels (pictorial elements)
  28. or rasters each having particular colour. In terms of computer hardware it
  29. means that some part of the memory contains huge array filled with numbers
  30. interpreted as colour of screen pixels. Changing those numbers triggers
  31. changes on the screen.
  32.  
  33. What should interactive graphics have? Well, it is plane we render on
  34. and the way our program reacts on actions, that is keyboard strikes
  35. or mouse moves. This is closely related to one other thing: execution
  36. flow. The reason we are talking of those things is: their implementation
  37. differ from one computer system to another and if graphic algorithms
  38. themselves are somewhat general, the way computer interfaces the screen or
  39. handles keyboard events is particular to every hardware on the market.
  40.  
  41. So what is the base of a hardware interface and how can we provide
  42. the common denominator for different architectures? Before answering
  43. let's consider how any interactive 3-D application works:
  44.  
  45. Since we want to see smooth motion whenever changing our position
  46. in the virtual world (or changes in the world itself), frames have to
  47. be completely composed when appearing on screen. We don't really want
  48. to see the process how polygons or lines appear one after another. What
  49. is being done instead is rendering frame in an off screen buffer, and
  50. then blitting completely composed frame on the actual visible surface.
  51. And no surprise here, the way different systems handle screen accesses
  52. does indeed vary. In case of MS-DOS the physical screen memory can be
  53. accessed directly. On the other hand when creating MS-WINDOWS,OS/2,
  54. X-WINDOWS or NeXTStep applications we can't really write directly to
  55. the screen. The memory protection simply won't allow that, so instead
  56. different API (Application Interface) functions delegating tasks to the
  57. operation system have to be called. (There actually are ways, to bypass
  58. some operation systems, but that is more of an exception then a general
  59. way to do things).
  60.  
  61. Similar to that we can access keyboard hardware directly in, say,
  62. MS-DOS, but hardly under MS-WINDOWS or X-WINDOWS or NeXTStep. Later
  63. on the other hand use similar "event" based approach to deal with,
  64. beside everything else, keyboard or mouse. That is, operation system
  65. would notify our application in pre-determined way if a key was pressed
  66. for instance.
  67.  
  68. We also have a bit of a problem finding common grounds in how
  69. different systems execute the code. "Event" based systems often
  70. presume that code must be executed as a function of occurred event.
  71. That is if button was pressed the code associated with this button
  72. is executed, this approach is used to the extreme in NeXTStep to
  73. lesser extend in MS-windows and to yet much smaller extend in X-Windows.
  74. On the other hand regular MS-DOS or in this matter UNIX application
  75. don't have built-in event mechanism, and the code is just being
  76. executed from the entry point until it exits (or until the operation
  77. system won't stand humiliation anymore and dumps core on us as UNIX
  78. or just simply freeze speechless as MS-DOS).
  79.  
  80. This constitutes two areas to write code particular to every
  81. system: screen/window management and event/execution management.
  82. (There are other things too, like sound for example, but I am 
  83. concentrating on those, interactive graphics related).
  84.  
  85.  
  86. Screen/window management.
  87. -------------------------
  88. Obviously we would need a function opening and closing the output,
  89. and since the way to proceed is to make all drawings into an off-screen
  90. buffer and then blit it, there must be a routine to take care of that.
  91. Now, the output plane itself would either be a hole physical screen or
  92. a window allocated by an operation system. Effectively for us the off-screen
  93. buffer would be the video memory. This buffer we would also be calling a
  94. "colourmap". Few assumptions are to be made about it's format. Every
  95. screen/window pixel has to have a colour value associated with it. This
  96. value can actually be composed of bits located in different parts of the
  97. screen buffer/colourmap - so called planar format, or bunched together in
  98. bytes or words each carrying number of colour for some pixel - so called
  99. flat format. Different computers would have screen memory and consequently
  100. colourmaps having different formats. Most would support several. For the
  101. simplicity we would from now on be considering just one format, well
  102. supported under different architectures: one byte per pixel flat colourmaps.
  103. The first byte in the colourmap would describe colour of the top rightmost
  104. pixel,
  105.  
  106.  
  107.     +-+-+-+-+
  108.     |G|R| ...                                  0x1,0x2,...,
  109.     +-+-+               +-----------+
  110.     |G| |            <--|  palette  |--        0x1,...,
  111.     +-+-+               |           |
  112.     | | |               |0x0 - Blue |          ....,
  113.     +-+-+-              |0x1 - Green|
  114.     | ...               |0x2 - Red  |
  115.                         |    ...    |
  116.     screen              |           |          screen memory
  117.                         +-----------+
  118.  
  119.                            pic 1.1
  120.  
  121. The next byte, second top pixel from the right and so on until the
  122. end of the line. From some point bytes would start describing pixels in
  123. the second line and so on, until the end of the colourmap. What we have
  124. is a one dimensional array covering two dimensional rectangular screen.
  125. One other thing - a palette description would allow us to establish 
  126. relation between values in the colourmap and physical colours on the 
  127. screen. In this case since we are dealing with one byte per pixel format, 
  128. there would be 256 possible values each byte can take and consequently 256
  129. different colours accessible at once. The colours would be described
  130. in RGB intensities: that is in components of Red, Green and Blue. 
  131. (There exist, actually, palettless colourmaps where RGB value is stored
  132. directly, and not via the palette) The bit sizes of components would be 
  133. different on different systems. And in some cases, some palette
  134. entries might be reserved for the operation system. Most of the time
  135. we can take care of that in the hardware interface, If for example we
  136. would decide working with 8bit per intensity we can make sure that 
  137. this value is readjusted inside the interface function to match particular 
  138. hardware format (If, for example, actual bit size is 6 bits we can take 
  139. only six leftmost bits from the intensity value and ignore two lower bits).
  140. It is now time to write prototypes for functions and structures we
  141. talked about:
  142.  
  143. struct HW_palette_cell
  144. {
  145.  int hw_r,hw_g,hw_b;
  146. };
  147.  
  148. int HW_open_screen(char display_name,struct HW_palette_cell palette[256],
  149.                    unsigned char *off_screen_buffer);
  150. void HW_blit(void);
  151. void HW_close_screen(void);
  152.  
  153. The first function, HW_open_screen, would either set a required screen
  154. mode under some systems, or allocate a window under other systems, the ASCII
  155. string display_name is added to accommodate X11, or any other hypothetical
  156. architecture supporting multiple displays. The array of HW_palette_cell
  157. structures would determine colours we would have associated with colourmap
  158. values for this screen/window, and the purpose of HW_blit and HW_close_screen
  159. functions is self-evident - copying colourmap into physical screen memory in
  160. case of HW_blit and deleting window or restoring original screen mode in case
  161. of HW_close_screen.
  162.  
  163.  
  164.  
  165. Event/execution management.
  166. ---------------------------
  167. Let's again take a look at how 3-D applications work. If it is an
  168. interactive game things on screen are happening all the time. And
  169. whether we apply pressure to the keyboard on not, we still can see if
  170. it is, say , a flight simulator the ground closing with increasing
  171. speed or some poignant creature drooling (best scenario) at us
  172. in some "Doom" style game. It all means that frames are being generated
  173. all the time. On the other hand code dealing with external exceptions
  174. like keyboard strikes is being executed only once such an event occurred.
  175. Some other kind of graphics application which doesn't involve motion
  176. may render frame only responding to an event and be idle otherwise.
  177. For example pressing arrow key to turn an object would cause the
  178. application to act and rerender the scene. What we are going to do
  179. would suit both situations.
  180.  
  181. void HW_run_event_loop(void (*APP_main)(void),
  182.                        void (*APP_key_hadler)(int key_code)
  183.                       );
  184. void HW_quit_event_loop(void);
  185.  
  186. Now, in HW_run_event_loop, APP_main is a pointer to a function where
  187. we want to have code associated with rendering of a frame. This function
  188. is to be called continuously, every time creating an image in the colourmap.
  189. The other one APP_key_handler is a pointer to a function which would be
  190. called when a key was pressed. It would be passed a code associated with
  191. this key. Back to described before two approaches, when we don't want
  192. to render frames all the time APP_main may contain no code at all, and
  193. APP_key_handeler would first deal with key pressed and then rerender
  194. the image. The second function: HW_quit_event_loop would basically signal
  195. HW_run_event_loop to exit and can be called from insides of either
  196. APP_main or APP_key_handler. The HW_run_event_loop is most likely to
  197. be implemented as a physical loop inside of which APP_main is unconditionally
  198. called, then check for occurred events made and on the condition that
  199. this check returns success APP_key_handler is called. That's why the
  200. name for similar schemes is: an "event loop".
  201.  
  202. There would be few definitions we would want to bring out in this
  203. hardware interface: Codes of keys to be passed into APP_key_handler
  204. for example, let's add few:
  205.  
  206.  
  207. #define HW_KEY_ARROW_LEFT    ...
  208. #define HW_KEY_ARROW_RIGHT   ...
  209. #define HW_KEY_ARROW_UP      ...
  210. #define HW_KEY_ARROW_DOWN    ...
  211.  
  212. #define HW_KEY_PLUS          ...
  213. #define HW_KEY_MINUS         ...
  214.  
  215. #define HW_KEY_ENTER         ...
  216.  
  217.  
  218. The dimensions, number of pixels along X and Y axes of the screen or
  219. window, also maximum values for both X and Y (that is one less then sizes
  220. along axes) and coordinates of the screen centre:
  221.  
  222.  
  223. #define HW_SCREEN_X_SIZE     ...
  224. #define HW_SCREEN_Y_SIZE     ...
  225. #define HW_SCREEN_X_MAX      ...
  226. #define HW_SCREEN_Y_MAX      ...
  227. #define HW_SCREEN_X_CENTRE   ...
  228. #define HW_SCREEN_Y_CENTRE   ...
  229.  
  230.  
  231. One other thing would relate to hardware as well as compiler differences -
  232. bit length of numbers. Most of the time we would be using default int
  233. size not carrying much as to it's bit length. On few occasions however
  234. it would be important to deal with, say, 32bit integers. The problem is
  235. that with some compilers such a number would be a regular int, but with
  236. other compilers it might be called long int whereas regular int would
  237. have size of 16bit. Let's add in the interface a typedef to describe 32bit
  238. and 16bit signed and unsigned numbers.
  239.  
  240.  
  241. typedef ... signed_16_bit;
  242. typedef ... signed_32_bit;
  243. typedef ... unsigned_16_bit;
  244. typedef ... unsigned_32_bit;
  245.  
  246.  
  247. Although it all is to a large degree a simplification, functionally it 
  248. would allow us to hide particular qualities of most systems within 
  249. those 5 interface functions and few definitions, allowing to write 
  250. machine independent code, and even nicer, to think more in terms 
  251. of algorithms and less in terms of hardware we are lucky to have 
  252. access to.
  253.  
  254.  
  255.  
  256. MS-DOS.
  257. -------
  258. MS-DOS is one of today's favorite operation systems of game
  259. programmers, and no, not because it is particularly good, only
  260. because it is not that much of a system, controlling very little
  261. and allowing to override itself in every inhuman way invented.
  262. the only problem, there are quite a few different C compilers
  263. on the PC market each of them having particular qualities
  264. having to be addressed. Of most popular there are: Turbo C/C++,
  265. Borland C/C++ from Borland international, Visual C/C++ from
  266. Microsoft, Watcom C , and finally my favorite ( read: the best )
  267. DJGPP a shareware port of unixy GNU C to MSDOS by DJ Delorie.
  268.  
  269. The problem with MSDOS is that it is essentially 16bit operation
  270. system, and a program under it uses segmented memory access
  271. so that the address of a location in memory is contained in two
  272. registers: base register has a number of 16byte paragraph within
  273. 1meg of total allowed memory and another register contain an
  274. offset from that position. It means that if we want to address
  275. more than 64K of memory (maximum value of bytes one can fit in 16bit
  276. address) we have to change value in the base register. this quite an
  277. ugly scheme causes compiler manufacturers to invent notions of
  278. memory models and other weird stuff to fit in. Until recently
  279. Borland and to my best knowledge Microsoft compilers would produce
  280. only 16bit MS-DOS code. Accessing extended memory (memory above
  281. 1meg) from such code might be tricky, trying to fit an application
  282. within 640K of total DOS memory can be tricky too.
  283.  
  284. On the other hand today, we have an option of choosing 32bit
  285. compiler for MS-DOS, either latest releases of Borland and
  286. MS supporting as an option 32bit code for MS-DOS. or Watcom C
  287. and DJGPP which were doing it for a while already. 32bit compilers
  288. produce code taking advantage of protected addressing modes of i386+
  289. based computers. they make executables to work under DOS extenders,
  290. programs that would switch processor into protected mode and manage
  291. memory addressing from then on. In most cases "flat" addressing is
  292. used which means that any location is addressed by a value located
  293. in one 32bit register. no more array size problems with that (in
  294. reality processor would use even more strange scheme then with plane
  295. 8086 mode segmentation but effectively it is flat mode for the program).
  296. DOS-extenders take care of extended memory so for a programmer there is just
  297. a big flat memory composed in reality from different kinds of RAM.
  298.  
  299. Under MS-DOS video RAM can be directly accessed. first we would
  300. have to set a screen mode using interrupts (preferred) or direct
  301. manipulations with video cards (not recommended). And after
  302. that all we would be writing to the video memory would be
  303. reflected on the screen. the address of VGA (Video Graphics Array-
  304. card mostly used today and allowing 256 colours modes) video-RAM
  305. is 0xa000:0x0000 (base:offset). DOS-extenders rearrange memory for
  306. flat 32bit accesses so it would appear to be in 0xa0000 in case of
  307. dos4gw dos-extender from Rational Systems used together with
  308. Watcom C or in 0xd0000000 in case of go32 extender used in DJGPP.
  309.  
  310. Implementations for event handling can either be quite tricky or
  311. extremely simple. The right way to do it is writing our own
  312. code for int 9h, hardware interrupt, the one being caused by keyboard
  313. hardware responding to what is happening with keys. Simple way is
  314. delegating those tasks to operation system, (or to C stdlib
  315. function, which would do delegating for us). This later approach is
  316. used in the enclosed code. This code covers 3 compilers we talked
  317. about: Turbo/Borland C++, Watcom C, DJGPP-GNU C. The former , Turbo C,
  318. is a 16 bit compiler, later are 32 bit compilers, and they are preferable
  319. to use for fast graphics, however, especially GNU C, lacks a bit in
  320. terms of friendliness which is needed by less experienced users.
  321.  
  322.  
  323.  
  324. MS-WINDOWS.
  325. -----------
  326. It is not my particular purpose to judge, but the reality is, MS-windows
  327. is yet to achieve reputation as a system for fast 3D graphics.
  328. (I guess it should read: "for fast anything") Still it might
  329. (then again, it might not). The program under MS-windows works
  330. quite different from the one under MS-DOS. Windows has an extensive
  331. set of API functions an application should use in order to access
  332. resources or perform actions. The messages from the operation system
  333. including information of events occurred are sent to special functions
  334. which we have to write for some of the windows we would want to open.
  335.  
  336. We can't write directly to the screen, what we can do is to call
  337. a windows API bitblit function to do it for us.
  338.  
  339. The windows application has to have few distinct parts: a
  340. WinMain -entry point function, one or several WndProc functions,
  341. that's the ones being called by windows when it feels like
  342. to send an event. In order to create a window program has
  343. to register some structure which would be shared by all
  344. instances of this window. After that we can call a CreateWindow
  345. function specifying geometry and style of this particular instance.
  346. The memory where we would be making all drawings has to be associated
  347. with a bitmap structure.
  348.  
  349. There is one a bit tricky thing- how to manage the palette. The problem
  350. is that there might be several colour intensive application active, but
  351. hardware has only limited number of palette registers, hence colours
  352. accessible at once. To partly solve this problem Windows reserve 20 
  353. colours by calling them "system". They would be 10 first and 10 last
  354. colours of 256 available in 8bit modes. They are used to paint boarders 
  355. menus etc. Those can be changed also (except for two: pure black and white) 
  356. but I would recommend against doing so. In a lot of instances going from 256 
  357. to 236 colours doesn't make that much of a difference.
  358.  
  359. How a windows application work? The execution starts from WinMain function.
  360. From here we would call all the initialization routines and finally start
  361. the "event loop". In the event loop we retrieve next event from the queue,
  362. translates the "virtual" key codes (whatever that might mean). After that 
  363. the event is forwarded to particular WndProc - an event handling routine. 
  364. Since windows v3.1 don't have true multitasking one has to be careful 
  365. with implementing this event loop. The only way for other applications 
  366. to get served is from within our calls to GetMessage or PeekMessage. It 
  367. is not quite a good idea to locate function calls inside event loop, what 
  368. can be done instead is putting those calls into WndProc function and making 
  369. sure from within the loop that required message would be send. The enclosed 
  370. implementation code is doing just that to manage the control flow.
  371.  
  372.  
  373.  
  374. X11.
  375. ----
  376. The beauty of X-windows - it is first of all an established protocol
  377. implementation of X on any hardware should abide to. So programs written
  378. on one UNIX machine supporting X would most likely recompile and execute
  379. just fine on some other. It also allows features such as remote clients,
  380. when a program is being actually executing on one computer and the graphics
  381. output it produces is being shown on another one via the network.
  382.  
  383. X-windows function in the following way: X-server running on a particular
  384. workstation accepts requests from local X-applications or actually those
  385. running on the remote computers and executes requests allowing applications
  386. to display graphics or text.
  387.  
  388. The majority of definition an application would need are concentrated
  389. in X11.h header file, functions defined there are located in libX11.a
  390. a library which should be linked together with any X application.
  391.  
  392. The way to implement our hardware interface functions is extremely
  393. straightforward and short, unlike another previously described windowing
  394. system we wouldn't want (although should) point accusing finger upon.
  395. Blitting is achieved by XPutImage function. The event loop is exactly
  396. what it is- checking for events, and calling functions depending on the
  397. event queue state.
  398.  
  399.  
  400.  
  401. NeXTStep.
  402. ---------
  403. NeXTStep first appeared together with NeXT inc. proprietary hardware
  404. which was based on 68040 Motorola processors. From some time in the past
  405. this powerful operation system became available for IBM PC compatible
  406. computers with i386+ processors and later for HP hardware. I believe today 
  407. it has been ported to other architectures as well. NeXTStep contains a 
  408. windowing system functioning on top of Mach-O UNIX-like operation system.
  409.  
  410. Unlike previously described systems NeXTStep is internally object-oriented.
  411. Majority of things on the screen are indeed managed as objects. NeXTStep
  412. applications would usually be written using objective-C (an object oriented
  413. extension for C, completely different from C++ ). A lot of things 
  414. (almost everything ) when creating an application interface can be done 
  415. visually without writing a single line of code. Tools provided allow to 
  416. manage projects very efficiently. But everything which is being done 
  417. visually can also be achieved just by writing code ( as inefficient as 
  418. it might sound ).
  419.  
  420. The majority of objects provided in developers kit would have outlets
  421. to place our own functions into, for example we would usually define a
  422. function to be associated with a button, this function would be called
  423. when this button is pressed. The windowing manager is making sure the
  424. events are flowing to particular objects, but nevertheless we can check
  425. the event queue ourselves and there are also provisions for functions
  426. which should be executed on the timing basis.
  427.  
  428. This operation system provides a great developer's platform, perhaps
  429. the most convenient there is today. 
  430.  
  431. As to the overall power, convenience and ease of use of different platforms, 
  432. I suggest browsing enclosed .c codes of hardware interfaces counting their 
  433. lengths and occurrences of places impossible to understand sober, ...guess
  434. who comes out looser?...
  435.  
  436.  
  437.                                   * * *